<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  <title>Volley 网络通讯框架一之发起请求 | 清风向阳</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  
    <meta name="keywords" content="Joker,Joker's Blog" />
  
  <meta name="description" content="Android系统给我们提供了一些最直接的HTTP库，和相关的工具类，AsyncTaskLoader，HttpURLConnection，AsyncTask，HTTPClient（Apache）等等，这些东西在使用的时候都没有系统性的管理者，导致在一个APP中很难有效的去管理请求，而且我们也会对除请求之外的事情也要关心，基于此，我们可能需要一个框架来统一我们的网络请求。">
<meta name="keywords" content="volley">
<meta property="og:type" content="article">
<meta property="og:title" content="Volley 网络通讯框架一之发起请求">
<meta property="og:url" content="http://mjjde.github.io/2015/12/11/Volley-网络通讯框架一之发起请求/index.html">
<meta property="og:site_name" content="清风向阳">
<meta property="og:description" content="Android系统给我们提供了一些最直接的HTTP库，和相关的工具类，AsyncTaskLoader，HttpURLConnection，AsyncTask，HTTPClient（Apache）等等，这些东西在使用的时候都没有系统性的管理者，导致在一个APP中很难有效的去管理请求，而且我们也会对除请求之外的事情也要关心，基于此，我们可能需要一个框架来统一我们的网络请求。">
<meta property="og:image" content="http://img.blog.csdn.net/20130929130854328">
<meta property="og:updated_time" content="2017-09-15T07:00:41.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Volley 网络通讯框架一之发起请求">
<meta name="twitter:description" content="Android系统给我们提供了一些最直接的HTTP库，和相关的工具类，AsyncTaskLoader，HttpURLConnection，AsyncTask，HTTPClient（Apache）等等，这些东西在使用的时候都没有系统性的管理者，导致在一个APP中很难有效的去管理请求，而且我们也会对除请求之外的事情也要关心，基于此，我们可能需要一个框架来统一我们的网络请求。">
<meta name="twitter:image" content="http://img.blog.csdn.net/20130929130854328">
  
  
    <link rel="icon" href="/favicon_pic.ico">
  
  <link href="//cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
  <link rel="stylesheet" href="/css/style.css">
  <script src="/js/pace.min.js"></script>
  

  
  

</head>

<body>
  <div id="container">
      <header id="header">
    <div id="banner"></div>
    <div id="header-outer">
        <div id="header-menu" class="header-menu-pos animated">
            <div class="header-menu-container">
                <a href="/" class="left">
                    <span class="site-title">Joker&#39;s Blog</span>
                </a>
                <nav id="header-menu-nav" class="right">
                    
                    <a  href="/">
                        <i class="fa fa-home"></i>
                        <span>Home</span>
                    </a>
                    
                    <a  href="/archives">
                        <i class="fa fa-archive"></i>
                        <span>Archives</span>
                    </a>
                    
                    <a  href="/about">
                        <i class="fa fa-user"></i>
                        <span>About</span>
                    </a>
                    
                </nav>
                <a class="mobile-header-menu-button">
                    <i class="fa fa-bars"></i>
                </a>
            </div>
        </div>
        <div id="header-row">
            <div id="logo">
                <a href="/">
                    <img src="/images/avatar.jpg" alt="logo">
                </a>
            </div>
            <div class="header-info">
                <div id="header-title">
                    
                    <h2>
                        Joker&#39;s Blog
                    </h2>
                    
                </div>
                <div id="header-description">
                    
                    <h3>
                        一个认真的技术博客
                    </h3>
                    
                </div>
            </div>
            <nav class="header-nav">
                <div class="social">
                    
                        <a title="Joker"  href="//joker-studio.pub">
                            <i class="fa fa-home fa-2x"></i></a>
                    
                        <a title="Github" target="_blank" href="//github.com/mjjde">
                            <i class="fa fa-github fa-2x"></i></a>
                    
                </div>
            </nav>
        </div>
    </div>
</header>
      <div class="outer">
        <section id="main" class="body-wrap"><article id="post-Volley-网络通讯框架一之发起请求" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 class="post-title" itemprop="name">
      Volley 网络通讯框架一之发起请求
    </h1>
    <div class="post-title-bar">
      <ul>
          
              <li>
                  <i class="fa fa-book"></i>
                  
                      <a href="/categories/Android技术/">Android技术</a>
                  
              </li>
          
        <li>
          <i class="fa fa-calendar"></i>  2015-12-11
        </li>
        <li>
          <i class="fa fa-eye"></i>
          <span id="busuanzi_value_page_pv"></span>
        </li>
      </ul>
    </div>
  

          
      </header>
    
    <div class="article-entry post-content" itemprop="articleBody">
      
            
            <blockquote>
<p>Android系统给我们提供了一些最直接的HTTP库，和相关的工具类，AsyncTaskLoader，HttpURLConnection，AsyncTask，HTTPClient（Apache）等等，这些东西在使用的时候都没有系统性的管理者，导致在一个APP中很难有效的去管理请求，而且我们也会对除请求之外的事情也要关心，基于此，我们可能需要一个框架来统一我们的网络请求。<br><a id="more"></a><br>所以网络框架的出现也就顺理成章了，接下来就给大家介绍一下Googol出品的volley框架。</p>
</blockquote>
<p>发布时间是2013年的IO大会，并且配上了下面的一张宣传图</p>
<p><img src="http://img.blog.csdn.net/20130929130854328" alt="volley"></p>
<p>图片里是发射火弓箭的图，有点类似流星，这里也是表明了volley框架的特点</p>
<ol>
<li>JSON，图像等的异步下载</li>
<li>网络请求的排序</li>
<li>网络请求的优先级处理</li>
<li>缓存</li>
<li>多级别取消请求</li>
<li>和Activity和生命周期的联动（Activity结束时同时取消所有网络请求）</li>
</ol>
<p>本篇我们会从源码的角度去分析volley网络框架的请求发起的过程</p>
<h4 id="Volley-java"><a href="#Volley-java" class="headerlink" title="Volley.java"></a><a href="#Volley-java" title="Volley.java"></a>Volley.java</h4><p>如果没有源码可以看着里<a href="https://github.com/mcxiaoke/android-volley/blob/master/src/main/java/com/android/volley/toolbox/Volley.java" target="_blank" rel="external">Guthub For Volley</a></p>
<p>首先我们看下Volley.java，这个类算是我们框架的入口了。</p>
<p>这个是该类的主要方法，其他的构造最后都是调用这个的。<br>其实是要创建一个RequestQueue对象，而要new 这个对象是需要2个参数的一个是继承了Cache的硬盘缓存对象，一个是继承了Network的网络处理对象，这个我们后面在详细说明，接下来我们要说的是DiskBasedCache和RequestQueue；</p>
<h4 id="RequestQueue-java"><a href="#RequestQueue-java" class="headerlink" title="RequestQueue.java"></a><a href="#RequestQueue-java" title="RequestQueue.java"></a>RequestQueue.java</h4><p>如果没有源码可以看着里<a href="https://github.com/mcxiaoke/android-volley/blob/master/src/main/java/com/android/volley/RequestQueue.java" target="_blank" rel="external">Guthub For RequestQueue.java</a></p>
<p>我们看到在Volley中创建了RequestQueue，并且调用了 <strong>start()</strong> 方法，其实该方法实现的目的就和方法名一样，首先调用stop方法来确保Dispatcher已经是停止的，然后开启我们处理request的两个Dispatcher。这两个Dispatcher我们后面在说。<br>我们再来看下这里的另一个重要的方法 <strong>add(Request <t>request)</t></strong> ;既然启动了Dispatcher，那么我们当然要加入要执行的request了。<br>它主要工作是：</p>
<ol>
<li>将request加入到 <em>HashSet<request<?>&gt; mCurrentRequests</request<?></em> 用来存放正在要处理的request</li>
<li>判断request是否需要被缓存，如果不是就直接放入 <em>PriorityBlockingQueue<request<?>&gt; mNetworkQueue</request<?></em> 中，而这个队列就是两个Dispatcher其中的NetworkDispatcher要take的队列</li>
<li>这一步是个优化点：根据request拿到CacheKey 也就是我们以后缓存的句柄，如果 <em>Map<string, queue<request<?="">&gt;&gt; mWaitingRequests</string,></em> 包含该句柄说明在mWaitingRequests里面有相同的request请求，那么既然是相同的请求，我们就只要请求到一个request就等于访问了所有的request。</li>
</ol>
<p>根据add这个方法的具体实现那么肯定得有一个request结束后对mWaitingRequests存放的相同的request的处理，那么我们就来看下 <strong>finish(Request <t>request)</t></strong> 这个方法</p>
<ol>
<li>移除 <em>HashSet<request<?>&gt; mCurrentRequests</request<?></em> 存放的request</li>
<li>调用onRequestFinished回调</li>
<li>如果request是需要缓存的，将mWaitingRequests相同的request请求全部取出再放入 <em>PriorityBlockingQueue<request<?>&gt; mCacheQueue</request<?></em> 缓存队列里，因为已经经过一次成功的request请求了，必定会有缓存，所以这里就全部走缓存队列</li>
</ol>
<p>好了RequestQueue中主要的方法已经走完了，现在来看下DiskBasedCache</p>
<h4 id="DiskBasedCache-java"><a href="#DiskBasedCache-java" class="headerlink" title="DiskBasedCache.java"></a><a href="#DiskBasedCache-java" title="DiskBasedCache.java"></a>DiskBasedCache.java</h4><p>如果没有源码可以看着里<a href="https://github.com/mcxiaoke/android-volley/blob/master/src/main/java/com/android/volley/toolbox/DiskBasedCache.java" target="_blank" rel="external">Github For DiskBasedCache.java</a></p>
<p>DiskBasedCache是volley给我们提供的默认缓存策略，当然你也可以自己实现自己的硬盘缓存，比如LruDiskCache，只要实现<a href="https://github.com/mcxiaoke/android-volley/blob/master/src/main/java/com/android/volley/Cache.java" target="_blank" rel="external">Cache</a>接口，就可以做到扩展了，现在我们就对其进行分析</p>
<ol>
<li>Disk的缓存一般都会以文件的形式存储在本地,那么就需要Directory,还有一个缓存必定会有一个容量的，不然其内存一直增加，最终会。。<br>我们看到构造方法 <strong>DiskBasedCache(File rootDirectory, int maxCacheSizeInBytes)</strong> 好了两个条件都具备了，maxCacheSizeInBytes提供了默认大小_DEFAULT_DISK_USAGE<em>BYTES = 5 M;</em></li>
<li>既然我们的缓存文件都会在文件里那么一开始我们必定要将已经缓存的文件读出来，也就是初始化 <strong>initialize()</strong>，该方法首先对文件目录进行判断，然后listFiles()读出所以的文件，遍历读出流，我们看到 <strong>CacheHeader entry = CacheHeader.readHeader(fis);</strong> 这个方法的调用，其实该缓存策略是包含2个部分的，一部分是保存了CacheHeader在内存中，一部分是保存了具体内容在文件里，而CacheHeader对象里保存的是头部信息，并没有实体。我们知道内存检索的速度是快于IO文件操作的，这样一来就提高的缓存查找的速度，刚刚上面的那个方法是CacheHeader的一个静态方法，它的目的是用来读取文件流中保存的头部信息，也就是说CacheHeader中得属性都是按一定格式存放在了文件的头部，CacheHeader中包括一些额外信息如文件大小，和请求返回后的一些头信息等。刚刚说的一定的格式我们可以从CacheHeader的 <strong>writeHeader()</strong> 和 <strong>readHeader()</strong> 看出来。取出的CacheHeader我们会存放在 <em>Map <string, cacheheader="">mEntries</string,></em> 中.</li>
<li>初始化完后我们要关心的当然是如何存放，如何读取。我们来看第一个方法 <strong>put(String key, Entry entry)</strong> 该方法是用来存放缓存的，上面说过了，缓存都是有具体内存的，那么我们要存放一个缓存的时候，就要检查内存大小 <strong>pruneIfNeeded(int neededSpace)</strong> :判断mTotalSize总和加上传参进来的大小是否超过总内存大小，如果超过了，那么就得删除其他的缓存，那么删除的策略是什么样呢，我们看到其实mEntries集合是采用Lru策略的，即最近最不常使用。我们取出一个最不常用的缓存对象，删除后，再判断，一直做while循环。</li>
<li>读取 <strong>get(String key)</strong> 该方法是用来读取的。首先会在内存中检索是否有缓存，如果有的话，根据key拿到包含数据的File，读取后得到一个Entity</li>
</ol>

            <div class="post-copyright">
    <div class="content">
        <p>最后更新： 2017年09月15日 15:00</p>
        <p>原始链接： <a class="post-url" href="/2015/12/11/Volley-网络通讯框架一之发起请求/" title="Volley 网络通讯框架一之发起请求">http://mjjde.github.io/2015/12/11/Volley-网络通讯框架一之发起请求/</a></p>
        <footer>
            <a href="http://mjjde.github.io">
                <img src="/images/avatar.jpg" alt="Joker Mei">
                Joker Mei
            </a>
        </footer>
    </div>
</div>

      
    </div>
    <footer class="article-footer">
        
        
<div class="post-share">
    <a href="javascript:;" id="share-sub" class="post-share-fab">
        <i class="fa fa-share-alt"></i>
    </a>
    <div class="post-share-list" id="share-list">
        <ul class="share-icons">
          <li>
            <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=http://mjjde.github.io/2015/12/11/Volley-网络通讯框架一之发起请求/&title=《Volley 网络通讯框架一之发起请求》 — 清风向阳&pic=http://mjjde.github.ioimages/avatar.jpg" data-title="微博">
              <i class="fa fa-weibo"></i>
            </a>
          </li>
          <li>
            <a class="weixin share-sns" id="wxFab" href="javascript:;" data-title="微信">
              <i class="fa fa-weixin"></i>
            </a>
          </li>
          <li>
            <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://mjjde.github.io/2015/12/11/Volley-网络通讯框架一之发起请求/&title=《Volley 网络通讯框架一之发起请求》 — 清风向阳&source=
Android系统给我们提供了一些最直接的HTTP库，和相关的工具类，AsyncTaskLoader，HttpURLConnection，AsyncTa..." data-title="QQ">
              <i class="fa fa-qq"></i>
            </a>
          </li>
          <li>
            <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://mjjde.github.io/2015/12/11/Volley-网络通讯框架一之发起请求/" data-title="Facebook">
              <i class="fa fa-facebook"></i>
            </a>
          </li>
          <li>
            <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《Volley 网络通讯框架一之发起请求》 — 清风向阳&url=http://mjjde.github.io/2015/12/11/Volley-网络通讯框架一之发起请求/&via=http://mjjde.github.io" data-title="Twitter">
              <i class="fa fa-twitter"></i>
            </a>
          </li>
          <li>
            <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=http://mjjde.github.io/2015/12/11/Volley-网络通讯框架一之发起请求/" data-title="Google+">
              <i class="fa fa-google-plus"></i>
            </a>
          </li>
        </ul>
     </div>
</div>
<div class="post-modal wx-share" id="wxShare">
    <a class="close" href="javascript:;" id="wxShare-close">×</a>
    <p>扫一扫，分享到微信</p>
    <img src="//api.qrserver.com/v1/create-qr-code/?data=http://mjjde.github.io/2015/12/11/Volley-网络通讯框架一之发起请求/" alt="微信分享二维码">
</div>

<div class="mask"></div>

        
        <ul class="article-footer-menu">
            
            
  <li class="article-footer-tags">
    <i class="fa fa-tags"></i>
      
    <a href="/tags/volley/" class="color2">volley</a>
      
  </li>

        </ul>
        
    </footer>
  </div>
</article>


    <aside class="post-toc-pos post-toc-top" id="post-toc">
        <nav class="post-toc-wrap">
            <ol class="post-toc"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#Volley-java"><span class="post-toc-text">Volley.java</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#RequestQueue-java"><span class="post-toc-text">RequestQueue.java</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#DiskBasedCache-java"><span class="post-toc-text">DiskBasedCache.java</span></a></li></ol>
        </nav>
    </aside>
    

<nav id="article-nav">
  
    <a href="/2015/12/11/Volley-网络通讯框架二之处理请求/" id="article-nav-newer" class="article-nav-link-wrap">

      <span class="article-nav-title">
        <i class="fa fa-hand-o-left" aria-hidden="true"></i>
        
          Volley-网络通讯框架二之处理请求
        
      </span>
    </a>
  
  
    <a href="/2015/12/09/github-hexo构建自己的博客/" id="article-nav-older" class="article-nav-link-wrap">
      <span class="article-nav-title">github+hexo构建自己的博客</span>
      <i class="fa fa-hand-o-right" aria-hidden="true"></i>
    </a>
  
</nav>



    
</section>
        
      </div>
      <footer id="footer">
  <div class="outer">
    <div id="footer-info" class="inner">
      
<p>
    <span id="busuanzi_container_site_uv" style='display:none'>
        总访客数：<span id="busuanzi_value_site_uv"></span>
    </span>
    <span id="busuanzi_container_site_pv" style='display:none'>
        总访问量：<span id="busuanzi_value_site_pv"></span>
    </span>
</p>


      <p>
        Powered by  <a href="http://hexo.io/" target="_blank">Hexo</a>
        Theme <a href="//github.com/wongminho/hexo-theme-miho" target="_blank">MiHo</a>
      &copy; 2018 Joker Mei<br>
      </p>
    </div>
  </div>
</footer>
    <script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<script src="//cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
  var mihoConfig = {
      root: "http://mjjde.github.io",
      animate: false,
      isHome: false,
      share: true
  }
</script>
<div class="sidebar">
    <!-- <div id="sidebar-search" title="Search">
        <i class="fa fa-search"></i>
    </div> -->
    <div id="sidebar-category" title="Categories">
        <i class="fa fa-book"></i>
    </div>
    <div id="sidebar-tag" title="Tags">
        <i class="fa fa-tags"></i>
    </div>
    <div id="sidebar-top">
        <span class="sidebar-top-icon"><i class="fa fa-angle-up"></i></span>
    </div>
</div>
<div class="sidebar-menu-box" id="sidebar-menu-box">
    <div class="sidebar-menu-box-container">
        <div id="sidebar-menu-box-categories">
            <a class="category-link" href="/categories/Android技术/">Android技术</a><a class="category-link" href="/categories/其他技术/">其他技术</a><a class="category-link" href="/categories/网络技术/">网络技术</a><a class="category-link" href="/categories/设计模式/">设计模式</a>
        </div>
        <div id="sidebar-menu-box-tags">
            <a href="/tags/Activity/" style="font-size: 10px;">Activity</a> <a href="/tags/Android/" style="font-size: 16px;">Android</a> <a href="/tags/Android-IPC/" style="font-size: 10px;">Android-IPC</a> <a href="/tags/Binder/" style="font-size: 16px;">Binder</a> <a href="/tags/DiskLruCache/" style="font-size: 10px;">DiskLruCache</a> <a href="/tags/Fragment/" style="font-size: 10px;">Fragment</a> <a href="/tags/HTTP/" style="font-size: 20px;">HTTP</a> <a href="/tags/Java/" style="font-size: 10px;">Java</a> <a href="/tags/Notification/" style="font-size: 10px;">Notification</a> <a href="/tags/RemoteView/" style="font-size: 10px;">RemoteView</a> <a href="/tags/Rxjava/" style="font-size: 14px;">Rxjava</a> <a href="/tags/ServiceManager/" style="font-size: 14px;">ServiceManager</a> <a href="/tags/android/" style="font-size: 12px;">android</a> <a href="/tags/gradle/" style="font-size: 10px;">gradle</a> <a href="/tags/java/" style="font-size: 18px;">java</a> <a href="/tags/other/" style="font-size: 10px;">other</a> <a href="/tags/volley/" style="font-size: 12px;">volley</a> <a href="/tags/widget/" style="font-size: 10px;">widget</a> <a href="/tags/事件/" style="font-size: 10px;">事件</a> <a href="/tags/组件化/" style="font-size: 10px;">组件化</a> <a href="/tags/设计模式/" style="font-size: 18px;">设计模式</a>
        </div>
    </div>
    <a href="javascript:;" class="sidebar-menu-box-close">&times;</a>
</div>
<div class="mobile-header-menu-nav" id="mobile-header-menu-nav">
    <div id="mobile-header-menu-container">
        <span class="title">Menu</span>
        <ul class="mobile-header-menu-navbar">
            
            <li>
                <a  href="/">
                    <i class="fa fa-home"></i><span>Home</span>
                </a>
            </li>
            
            <li>
                <a  href="/archives">
                    <i class="fa fa-archive"></i><span>Archives</span>
                </a>
            </li>
            
            <li>
                <a  href="/about">
                    <i class="fa fa-user"></i><span>About</span>
                </a>
            </li>
            
        </ul>
    </div>
</div>
<div class="search-wrap">
    <span class="search-close">&times;</span>
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="back">
            <i class="icon icon-lg icon-chevron-left"></i>
        </a>
        <input class="search-field" placeholder="Search..." id="keywords">
        <a id="search-submit" href="javascript:;">
            <i class="fa fa-search"></i>
        </a>
    <div class="search-container" id="search-container">
        <ul class="search-result" id="search-result">
        </ul>
    </div>
</div>

<div id="search-tpl">
    <li class="search-result-item">
        <a href="{url}" class="search-item-li">
            <span class="search-item-li-title" title="{title}">{title}</span>
        </a>
    </li>
</div>
<script src="/js/search.js"></script>
<script src="/js/main.js"></script>








  </div>
</body>
</html>